package pushup.view;

import java.util.ArrayList;
import java.util.LinkedList;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ViewPart;

import pushup.controller.PushUpController;
import pushup.model.Field;
import pushup.model.Type;
import pushup.view.providers.ViewContentProvider;
import pushup.view.providers.ViewLabelProvider;

public class PushUpView extends ViewPart {
	
	public static final String ID = "PushUp.view";
	
	private TableViewer viewer;
	private Action doubleClickAction;
	
	private void refresh() {
	    viewer.refresh();
	    Table table = viewer.getTable();
	    for (int i = 0, n = table.getColumnCount(); i < n; i++) {
	      table.getColumn(i).pack();
	    }
	    viewer.refresh();
	  }

	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	public void createPartControl(Composite parent) {
		viewer = new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider(PushUpController.getInstance().getStatistics()));
		viewer.setSorter(new NameSorter());
		
		ArrayList<Type> types = PushUpController.getInstance().getTypesWithSimilarities();
		 
		viewer.setInput(types);
		
		PushUpController.getInstance().setViewer(viewer);
		
		Table table = viewer.getTable();
	    new TableColumn(table, SWT.LEFT).setText("Class Name");
	    new TableColumn(table, SWT.CENTER).setText("Number of similar Classes");
	    new TableColumn(table, SWT.CENTER).setText("Maximum similarity");
	    new TableColumn(table, SWT.LEFT).setText("Best candidate");
	    new TableColumn(table, SWT.LEFT).setText("Similarities");
	    
	    table.setHeaderVisible(true);
	    //table.setLinesVisible(true);
	    
	    refresh();

		// Create the help context id for the viewer's control
		PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), "tabletest.viewer");
		makeActions();
		hookDoubleClickAction();
	}

	private void makeActions() {
		doubleClickAction = new Action() {
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection)selection).getFirstElement();				
				
				Type type = (Type)obj;
				IPath path = type.getPath();
				
				Type candidate = type.getBestCandidate();
				IPath candidatePath = candidate.getPath();
				
				if (path != null && candidatePath != null){					
					openEditor(ResourcesPlugin.getWorkspace().getRoot().findMember(path), candidate.getSimilarities().get(type));
					openEditor(ResourcesPlugin.getWorkspace().getRoot().findMember(candidatePath), type.getSimilarities().get(candidate));
				}			
						
			}

			private void openEditor(IResource resource, LinkedList<Field> linkedList) {
				if(resource != null && resource.exists() && resource.getType() == IResource.FILE) {
					try {
						IWorkbenchPage activePage =
								PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
						
						IDE.openEditor(activePage, (IFile) resource, true);
						
						for(Field similarField : linkedList){
							//editor.selectAndReveal(similarField.getStartingOffset(), similarField.getLength());

							try {
								IMarker marker = resource.createMarker("PushUp.SimilarMarker");
								marker.setAttribute(IMarker.CHAR_START,similarField.getStartingOffset());
								marker.setAttribute(IMarker.CHAR_END,similarField.getStartingOffset() +  similarField.getLength());
							} catch (CoreException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
						
						
						
					} catch (PartInitException e) {
						System.err.println("Exception while opening: " + resource);
					} 
				}
			}
		};
	}

	private void hookDoubleClickAction() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}
	
	public static void openView() {
		
		Display.getDefault().asyncExec(new Runnable() {
			
			public void run() {
				IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
				if(window == null){
					System.err.println("null window in ViewActionDelegate.openView()");
					return;
				}
				
				IWorkbenchPage page = window.getActivePage();
				if(page == null){
					System.err.println("null page in ViewActionDelegate.openView()");
					return;
				}
				
				// open the view
				try {
					IViewPart oldView = page.findView(ID);
					if(oldView != null){
						// found an old view
						window.getActivePage().hideView(oldView);
						//oldView.dispose();
					}
					page.showView(ID);
				} catch (PartInitException e) {
					System.err.println("Error while showing the view");
					e.printStackTrace();
				}
				
			}
		});
		
		
	}

}
